#include <GL/glfw.h>
#include "GlDrawer.h"
#include "ImageLoading.h"

using namespace cmn;
using namespace drawing;

namespace core {

	std::map<std::string, Texture> GlDrawer::m_textureStore;

	GlDrawer::GlDrawer( const Color& backgroud ) :
		m_pen( Color::Black(), 1, PenStyle::Solid ),
		m_brush( Color::Black(), BrushStyle::Solid )
	{
		glEnable( GL_COLOR_MATERIAL );
		glEnable( GL_BLEND );
		glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
		glEnable( GL_DEPTH_TEST );
		glEnable( GL_ALPHA_TEST );
		glEnable( GL_TEXTURE_2D );

		glClearColor( backgroud.R, backgroud.G, backgroud.B, backgroud.A );
		glClearDepth( 1.0f );

		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	}

	GlDrawer::GlDrawer( const GlDrawer& other ) :
		m_pen( other.m_pen ),
		m_brush( other.m_brush )
	{}

	GlDrawer::~GlDrawer() {}

	GlDrawer& GlDrawer::operator=( const GlDrawer& rhs ) {
		if( this == &rhs ) return *this;

		m_pen = rhs.GetPen();
		m_brush = rhs.GetBrush();

		return *this;
	}

	Pen GlDrawer::GetPen() const { return m_pen; }
	void GlDrawer::SetPen( const Pen& pen ) { m_pen = pen; }

	Brush GlDrawer::GetBrush() const { return m_brush; }
	void GlDrawer::SetBrush( const Brush& brush ) { m_brush = brush; }

	void GlDrawer::DrawPoint( const Vec2& point ) {
		UsePen( m_pen );

		glBegin( GL_POINT );
		glVertex2f( point.X, point.Y );
		glEnd();
	}

	void GlDrawer::DrawLine( const Vec2& start, const Vec2& end ) {
		UsePen( m_pen );

		glBegin( GL_LINES );
		glVertex2f( start.X, start.Y );
		glVertex2f( end.X, end.Y );
		glEnd();
	}


	void GlDrawer::DrawCircle( const Circle& circle ) {
		const float segments = 16.0f;
		const float increment = 2.0f * Pi / segments;
		float theta = 0.0f;

		UseBrush( m_brush );

		glBegin( GL_TRIANGLE_FAN );
		for( int i = 0; i < segments; ++i ) {
			Vec2 v = circle.Center + circle.Radius * Vec2( cosf( theta ), sinf( theta ) );
			glVertex2f( v.X, v.Y );
			theta += increment;
		}
		glEnd();

		UsePen( m_pen );

		glBegin( GL_LINE_LOOP );
		for( int i = 0; i < segments; ++i ) {
			Vec2 v = circle.Center + circle.Radius * Vec2( cosf( theta ), sinf( theta ) );
			glVertex2f( v.X, v.Y );
			theta += increment;
		}
		glEnd();
	}

	void GlDrawer::DrawPolygon( const Polygon& polygon ) {
		int count = polygon.GetVerticesCount();

		UseBrush( m_brush );

		glBegin( GL_TRIANGLE_FAN );
		for( int i = 0; i < count; ++i ) {
			Vec2 vertex = polygon[i];
			glVertex2f( vertex.X, vertex.Y );
		}
		glEnd();

		UsePen( m_pen );

		glBegin( GL_LINE_LOOP );
		for( int i = 0; i < count; ++i ) {
			Vec2 vertex = polygon[i];
			glVertex2f( vertex.X, vertex.Y );
		}
		glEnd();
	}

	void GlDrawer::DrawModel( const cmn::Transform& position, const drawing::Model* model ) {
		bool isTransparent;

		std::string textureFilename = model->GetTextureFilename();
		bool hasTexture = !textureFilename.empty();

		if( hasTexture ) {
			Texture texture = GetTexture( textureFilename );
			glBindTexture( GL_TEXTURE_2D, ( GLuint )texture.GlId );
			isTransparent = texture.GlFormat == GL_RGBA;
		}
		else
			isTransparent = false;

		bool isDepthTestEnabled = glIsEnabled( GL_DEPTH_TEST );

		if( isTransparent ) glDisable( GL_DEPTH_TEST );

		Material material = model->GetMaterial();

		glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &material.Ambient.R );
		glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &material.Diffuse.R );
		glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &material.Specular.R );
		glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, material.Shininess );
		// draw each face...

		Mesh* mesh = model->GetMesh();

		for( IteratorPtr<Face> facesIter( mesh->Faces ); !facesIter.IsEnd(); facesIter.Next() ) {
			Face face = facesIter.Current();

			int count = face.Vertices.GetLength();

			glColor3f( 1, 1, 0 );
			glBegin( GL_POLYGON );

			for( int i = 0; i < count; ++i ) {
				Vec3 pos = mesh->Positions[face.Vertices[i].PosIndex];
				Vec2 texCoord = mesh->TexCoords[face.Vertices[i].TexCoordIndex];
				Vec3 normal = mesh->Positions[face.Vertices[i].NormalIndex];

				glNormal3f( normal.X, normal.Y, normal.Z );
				if( hasTexture ) glTexCoord2f( texCoord.X, texCoord.Y );
				glVertex3f( pos.X, pos.Y, pos.Z );
			}

			glEnd();	//	GL_POLYGON

		}

		//	restore depth test
		if( isDepthTestEnabled )
			glEnable( GL_DEPTH_TEST );
		else
			glDisable( GL_DEPTH_TEST );

	}

	unsigned int GetGlPixelFormat( ImagePixelFormat imagePixelFormat ) {
		switch( imagePixelFormat ) {
			case ImagePixelFormat::Rgb:
				return GL_RGB;
			case ImagePixelFormat::Rgba:
				return GL_RGBA;
			default:
				return GL_RGBA;
		}
	}

	Texture GlDrawer::GetTexture( std::string filename ) {

		typename std::map<std::string, Texture>::iterator it = m_textureStore.find( filename );
		if( it != m_textureStore.end() )
			return ( *it ).second;

		const Image* image = LoadImage( filename );

		GLuint textureIndex;
		glGenTextures( 1, &textureIndex );

		unsigned int width = image->GetWidth();
		unsigned int height = image->GetHeight();
		ImagePixelFormat pixelFormat = image->GetPixelFormat();
		GLuint glPixelFormat = GetGlPixelFormat( pixelFormat );

		glBindTexture( GL_TEXTURE_2D, textureIndex ); // 2d texture (x and y size)
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // scale linearly when image bigger than texture
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); // scale linearly + mipmap when image smalled than texture
		gluBuild2DMipmaps( GL_TEXTURE_2D, glPixelFormat, width, height, glPixelFormat, GL_UNSIGNED_BYTE, image->GetRawData() );

		Texture texture( ( unsigned int ) textureIndex, ( unsigned int ) glPixelFormat );

		m_textureStore[filename] = texture;

		delete image;

		return texture;
	}

	void GlDrawer::UsePen( const Pen& pen ) {
		UseColor( pen.GetColor() );
		UsePenStyle( pen.GetStyle() );
		glLineWidth( GLfloat( pen.GetWidth() ) );
	}

	void GlDrawer::UseBrush( const Brush& brush ) {
		UseColor( brush.GetColor() );
		UseBrushStyle( brush.GetStyle() );
	}

	void GlDrawer::UseBrushStyle( BrushStyle brushStyle ) {
		switch( brushStyle ) {
			case BrushStyle::Solid:
				glDisable( GL_POLYGON_STIPPLE );
				break;
			case BrushStyle::Transparent:
				glDisable( GL_POLYGON_STIPPLE );
				glColor4f( 0.0f, 0.0f, 0.0f, 0.0f );
				break;
			case BrushStyle::HorizontalHatch:
				glEnable( GL_POLYGON_STIPPLE );
				glPolygonStipple( horizontalHatch );
				break;
			case BrushStyle::VerticalHatch:
				glEnable( GL_POLYGON_STIPPLE );
				glPolygonStipple( verticalHatch );
				break;
			case BrushStyle::CrossHatch:
				glEnable( GL_POLYGON_STIPPLE );
				glPolygonStipple( crossHatch );
				break;
			case BrushStyle::BdiagonalHatch:
				glEnable( GL_POLYGON_STIPPLE );
				glPolygonStipple( leftDiagHatch );
				break;
			case BrushStyle::FdiagonalHatch:
				glEnable( GL_POLYGON_STIPPLE );
				glPolygonStipple( rightDiagHatch );
				break;
			case BrushStyle::CrossdiagHatch:
				glEnable( GL_POLYGON_STIPPLE );
				glPolygonStipple( crossdiagHatch );
				break;
			case BrushStyle::Stipple:
				glEnable( GL_POLYGON_STIPPLE );
				glPolygonStipple( stipple );
				break;
			case BrushStyle::Unknown:
				glDisable( GL_POLYGON_STIPPLE );
				glColor4f( 0.0f, 0.0f, 0.0f, 0.0f );
				break;
		}
	}

	void GlDrawer::UsePenStyle( PenStyle penStyle ) {
		switch( penStyle ) {
			case PenStyle::Solid:
				glDisable( GL_LINE_STIPPLE );
				break;
			case PenStyle::Dashed:
				glEnable( GL_LINE_STIPPLE );
				glLineStipple( 2, 0x00ff );
				break;
			case PenStyle::DashDotted:
				glEnable( GL_LINE_STIPPLE );
				glLineStipple( 2, 0xffcc );
				break;
			case PenStyle::Unknown:
				glDisable( GL_LINE_STIPPLE );
				break;
		}
	}

	void GlDrawer::UseColor( const Color& color ) {
		glColor4f( color.R, color.G, color.B, color.A );
	}


	GLubyte GlDrawer::horizontalHatch[128] = {
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ), GLubyte( 0x00 ),
	};

	GLubyte GlDrawer::verticalHatch[128] = {
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
	};

	GLubyte GlDrawer::crossHatch[128] = {
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
		GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), GLubyte( 0xFF ), 	GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ),
	};

	GLubyte GlDrawer::leftDiagHatch[128] = {
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),
		GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ),
	};

	GLubyte GlDrawer::rightDiagHatch[128] = {
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ), GLubyte( 0x44 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ), GLubyte( 0x11 ),
	};

	GLubyte GlDrawer::crossdiagHatch[128] = {
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), GLubyte( 0x88 ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ), GLubyte( 0x22 ),		GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
	};

	GLubyte GlDrawer::stipple[128] = {
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
		GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), GLubyte( 0xAA ), 	GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ), GLubyte( 0x55 ),
	};
}
